function gemini_log($data) { $dir = WP_CONTENT_DIR . '/secure/logs'; $log_file = $dir . '/gemini-error.log'; // Ensure directory exists if (!is_dir($dir)) { wp_mkdir_p($dir); } $entry = "[" . date('Y-m-d H:i:s') . "] "; $entry .= print_r($data, true) . " "; // Try writing to file $ok = @file_put_contents($log_file, $entry, FILE_APPEND); // Fallback to PHP error_log if file write fails if ($ok === false) { $last = error_get_last(); error_log("GEMINI_LOG_WRITE_FAILED: " . print_r([ 'log_file' => $log_file, 'is_dir' => is_dir($dir), 'dir_writable' => is_writable($dir), 'file_exists' => file_exists($log_file), 'file_writable' => file_exists($log_file) ? is_writable($log_file) : null, 'last_error' => $last, 'data' => $data, ], true)); } } // Debug flag shared between handlers and http_api_debug hook $GLOBALS['gemini_debug_mode'] = $GLOBALS['gemini_debug_mode'] ?? false; function gemini_is_debug_mode() { // JSON requests may set the global flag explicitly inside handlers if (!empty($GLOBALS['gemini_debug_mode'])) { return true; } // Fallback for classic form/query param return (isset($_REQUEST['debug']) && ($_REQUEST['debug'] === '1' || $_REQUEST['debug'] === 1)); } // Low-level HTTP debug (logs request/response) - logs only when debug mode is enabled add_action('http_api_debug', function ($response, $context, $class, $args, $url) { if (!gemini_is_debug_mode()) { return; } $safe_args = [ 'method' => $args['method'] ?? null, 'timeout' => $args['timeout'] ?? null, 'headers' => $args['headers'] ?? null, ]; // Avoid logging huge bodies in debug hook if (isset($args['body'])) { $body = is_string($args['body']) ? $args['body'] : wp_json_encode($args['body']); $safe_args['body_len'] = is_string($body) ? strlen($body) : null; } $resp_payload = null; if (is_wp_error($response)) { $resp_payload = ['wp_error' => $response->get_error_message()]; } else { $resp_payload = [ 'code' => wp_remote_retrieve_response_code($response), 'headers' => wp_remote_retrieve_headers($response), 'body' => wp_remote_retrieve_body($response), ]; } gemini_log([ 'type' => 'http_api_debug', 'context' => $context, 'url' => $url, 'args' => $safe_args, 'response' => $resp_payload, ]); }, 10, 5); function my_get_gemini_access_token() { $json_path = WP_CONTENT_DIR . '/secure/gemini-service-account.json'; if (!file_exists($json_path)) { gemini_log(['type' => 'token_error', 'message' => 'Service account JSON not found', 'json_path' => $json_path]); return false; } $sa = json_decode(file_get_contents($json_path), true); if (!$sa || empty($sa['client_email']) || empty($sa['private_key'])) { gemini_log(['type' => 'token_error', 'message' => 'Invalid service account JSON (missing client_email/private_key)', 'json_path' => $json_path]); return false; } $now = time(); $jwt_header = rtrim(strtr(base64_encode(json_encode([ 'alg' => 'RS256', 'typ' => 'JWT' ])), '+/', '-_'), '='); $jwt_claim = rtrim(strtr(base64_encode(json_encode([ 'iss' => $sa['client_email'], 'scope' => 'https://www.googleapis.com/auth/generative-language', 'aud' => 'https://oauth2.googleapis.com/token', 'iat' => $now, 'exp' => $now + 3600, ])), '+/', '-_'), '='); $jwt_unsigned = $jwt_header . '.' . $jwt_claim; $signature = ''; $signed_ok = openssl_sign($jwt_unsigned, $signature, $sa['private_key'], 'sha256'); if (!$signed_ok) { gemini_log(['type' => 'token_error', 'message' => 'openssl_sign failed while creating JWT']); return false; } $jwt_signature = rtrim(strtr(base64_encode($signature), '+/', '-_'), '='); $jwt = $jwt_unsigned . '.' . $jwt_signature; $response = wp_remote_post('https://oauth2.googleapis.com/token', [ 'headers' => [ 'Content-Type' => 'application/x-www-form-urlencoded', ], 'body' => [ 'grant_type' => 'urn:ietf:params:oauth:grant-type:jwt-bearer', 'assertion' => $jwt, ], 'timeout' => 20, ]); if (is_wp_error($response)) { gemini_log(['type' => 'token_wp_error', 'error' => $response->get_error_message()]); return false; } $code = wp_remote_retrieve_response_code($response); $raw = wp_remote_retrieve_body($response); $body = json_decode($raw, true); if ($code !== 200) { gemini_log([ 'type' => 'token_http_error', 'http_code' => $code, 'raw_body' => $raw, 'parsed' => $body, ]); return false; } $token = $body['access_token'] ?? false; if (!$token) { gemini_log([ 'type' => 'token_error', 'message' => 'access_token missing in token response', 'raw_body' => $raw, 'parsed' => $body, ]); return false; } // Optional: log token acquisition only in debug mode (avoid noise) if (gemini_is_debug_mode()) { gemini_log(['type' => 'token_ok', 'http_code' => $code]); } return $token; } add_action('wp_ajax_send_to_gemini', 'handle_send_to_gemini'); add_action('wp_ajax_nopriv_send_to_gemini', 'handle_send_to_gemini'); function handle_send_to_gemini() { // ورودی هم با JSON و هم با فرم ساپورت شود $userData = null; $plansJson = null; $debug_mode = false; // اگر JSON باشد $content_type = strtolower($_SERVER['CONTENT_TYPE'] ?? ''); if (strpos($content_type, 'application/json') !== false) { $raw = file_get_contents('php://input'); $json = json_decode($raw, true); if (json_last_error() === JSON_ERROR_NONE && is_array($json)) { if (isset($json['userData'])) { $userData = sanitize_textarea_field($json['userData']); } if (isset($json['plansJson'])) { $plansJson = is_string($json['plansJson']) ? $json['plansJson'] : json_encode($json['plansJson'], JSON_UNESCAPED_UNICODE | JSON_UNESCAPED_SLASHES); } if (isset($json['debug'])) { $debug_mode = ($json['debug'] === '1' || $json['debug'] === 1 || $json['debug'] === true); } } } // اگر فرم POST کلاسیک باشد if (!$userData && isset($_POST['userData'])) { $userData = sanitize_textarea_field($_POST['userData']); } if (!$plansJson && isset($_POST['plansJson'])) { $plansJson = wp_unslash($_POST['plansJson']); } if (!$debug_mode && isset($_POST['debug'])) { $debug_mode = ($_POST['debug'] === '1'); } $GLOBALS['gemini_debug_mode'] = $debug_mode; // Read optional extra fields (name, phone, website, formId) $extraFields = array(); if (isset($_POST['extraFields'])) { $ef = json_decode(wp_unslash($_POST['extraFields']), true); if (is_array($ef)) { $extraFields = array( 'name' => isset($ef['name']) ? sanitize_text_field($ef['name']) : '', 'phone' => isset($ef['phone']) ? sanitize_text_field($ef['phone']) : '', 'website' => isset($ef['website']) ? esc_url_raw($ef['website']) : '', 'formId' => isset($ef['formId']) ? sanitize_text_field($ef['formId']) : '', ); } } if (!$userData) { wp_send_json_error(['message' => 'داده‌ای دریافت نشد']); } if (!$plansJson) { wp_send_json_error(['message' => 'لیست پلن‌ها ارسال نشد']); } // دیکد JSON پلن‌ها $plansArrayRaw = json_decode($plansJson, true); if (!is_array($plansArrayRaw)) { wp_send_json_error(['message' => 'فرمت JSON پلن‌ها معتبر نیست.']); } // نرمال‌سازی کلیدها برای پرامپت (کوچک نگه داشتن ورودی) $plansArray = []; foreach ($plansArrayRaw as $p) { $plansArray[] = [ 'planName' => $p['name'] ?? '', 'planType' => $p['type'] ?? '', 'location' => $p['location'] ?? '', 'datacenter' => $p['datacenter'] ?? '', 'cpu' => $p['cpu'] ?? '', 'ram' => $p['ram'] ?? '', 'storage' => $p['storage'] ?? '', 'bandwidth' => $p['traffic'] ?? '', 'disk' => $p['storage'] ?? '', 'price' => $p['price'] ?? '', 'pricePeriod'=> $p['price_period'] ?? '', 'priceFormatted' => isset($p['price']) ? number_format((int) $p['price'], 0, '.', ',') : '', 'buyLink' => $p['link'] ?? '', ]; } // در صورت خیلی زیاد بودن، یک سقف منطقی بگذاریم if (count($plansArray) > 200) { $plansArray = array_slice($plansArray, 0, 200); } $plansJsonMin = wp_json_encode($plansArray, JSON_UNESCAPED_UNICODE | JSON_UNESCAPED_SLASHES); // کلید و مدل // $api_key = 'AIzaSyCuMe-s-NxY3cFLHTX3IgW5MhzJLndpQaU'; // $url = 'https://generativelanguage.googleapis.com/v1beta/models/gemini-2.0-flash:generateContent?key=' . $api_key; // پیشفرض خالی $flexBackupMsg = ''; // پرامپت — فقط HTML خروجی $prompt = " نقش شما «مشاور زیرساخت» است. بر اساس ورودی کاربر و لیست پلن‌ها (به صورت JSON)، دقیقا یک پلن (VPS یا Dedicated) را انتخاب کنید. شرط: اگر کاربر گیمر نیست و ماهانه بالای 20000 کاربر دارد و خودش حرفه‌ای یا متخصص است و مانیتورینگ دائم دارد، از بین پلن‌های سرور اختصاصی گزینه مناسب را پیشنهاد بده در غیر اینصورت از بین پلن های سرور مجازی یکی را انتخاب کن. اگر چند گزینه مشابه دیدی، فقط بهترین را انتخاب کن و یک مورد برگردان. هیچ بلاک کد یا backtick ارسال نکن. فقط HTML خالص قابل رندر بده. - در خروجی، متن {{flexBackupMsg}} را بدون تغییر قرار بده. این متن را تو نباید پر کنی. هر جا unlimited هستش به جاش بنویس نامحدود [HTML قالب خروجی]

پیشنهاد هوشمند ما برای شما

با توجه به نیازمندی های شما و تحلیل پاسخ های شما توسط هوش مصنوعی ایران سرور، پلن زیر مناسب شما می باشد و تمام نیازمندی های شما را برطرف می‌کند

{{planName}}

{{flexBackupMsg}}

چتر آبی ایران‌سرور: پشتیبانی کامل و همیشه‌در‌دسترس

همیشه یک تیم فنی حرفه‌ای کنار شماست؛ از مانیتورینگ ۲۴ ساعته و پاسخ فوری زیر ۳۰ دقیقه، تا رفع فوری مشکلات امنیتی و فنی، مدیریت بکاپ‌ها، به‌روزرسانی‌ها و بهینه‌سازی سرور.

🚀 سفارش و خرید پلن
[اطلاعات کاربر] ".$userData." [لیست پلن‌ها — JSON فشرده] ".$plansJsonMin; $payload = json_encode([ 'contents' => [ ['parts' => [['text' => $prompt]]] ] ], JSON_UNESCAPED_UNICODE | JSON_UNESCAPED_SLASHES); $access_token = my_get_gemini_access_token(); if (!$access_token) { gemini_log(['type' => 'auth_error', 'message' => 'Failed to get access token']); // ✅ ارسال به گوگل شیت با وضعیت خطا send_to_gsheet_with_status($userData, '', 'خطا در احراز هویت', $extraFields); wp_send_json_error(['message' => 'خطا در دریافت Access Token از Google']); } $url = 'https://generativelanguage.googleapis.com/v1beta/models/gemini-2.0-flash:generateContent'; // Log connection attempt (for both services) gemini_log([ 'type' => 'gemini_connect', 'service' => 'v1', 'url' => $url, 'payload_len' => isset($payload) ? strlen($payload) : null, 'extraFields' => isset($extraFields) ? $extraFields : null, ]); $response = wp_remote_post($url, [ 'headers' => [ 'Content-Type' => 'application/json; charset=utf-8', 'Authorization' => 'Bearer ' . $access_token, // ✅ اضافه شد ], 'body' => $payload, 'timeout' => 45, ]); if (is_wp_error($response)) { gemini_log([ 'type' => 'wp_error', 'error' => $response->get_error_message(), ]); // ✅ ارسال به گوگل شیت با وضعیت خطا send_to_gsheet_with_status($userData, '', 'خطای شبکه: ' . $response->get_error_message(), $extraFields); wp_send_json_error([ 'message' => 'در پردازش درخواست خطایی رخ داد. لطفاً بعداً تلاش کنید.' ]); } $code = wp_remote_retrieve_response_code($response); $raw_body = wp_remote_retrieve_body($response); $headers = wp_remote_retrieve_headers($response); $body = json_decode($raw_body, true); // Log HTTP details when debug is enabled if (gemini_is_debug_mode()) { gemini_log([ 'type' => 'http_debug', 'service' => 'v1', 'http_code' => $code, 'headers' => $headers, 'raw_body' => $raw_body, ]); } // ✅ بررسی کد وضعیت HTTP if ($code !== 200) { gemini_log([ 'type' => 'api_error', 'http_code' => $code, 'headers' => $headers, 'raw_body' => $raw_body, 'response' => $body, ]); $error_msg = 'خطای API - کد ' . $code; // پیام‌های خطای رایج if ($code === 429) { $error_msg = 'محدودیت درخواست - سهمیه تمام شده'; } elseif ($code === 401 || $code === 403) { $error_msg = 'خطای احراز هویت - توکن نامعتبر'; } elseif ($code === 500 || $code === 503) { $error_msg = 'سرویس Gemini موقتاً در دسترس نیست'; } // Log successful response (minimal) gemini_log([ 'type' => 'gemini_ok', 'service' => 'v1', 'http_code' => $code, ]); // ✅ ارسال به گوگل شیت با وضعیت خطا send_to_gsheet_with_status($userData, '', $error_msg, $extraFields); wp_send_json_error([ 'message' => 'سرویس موقتاً در دسترس نیست.' ]); } // استخراج جواب (با fallback ایمن) $reply = ''; if (isset($body['candidates'][0]['content']['parts'][0]['text'])) { $reply = $body['candidates'][0]['content']['parts'][0]['text']; } elseif (!empty($body['candidates'][0]['content']['parts'])) { foreach ($body['candidates'][0]['content']['parts'] as $part) { if (!empty($part['text'])) { $reply = $part['text']; break; } } } if ($reply) { // حذف ```html و ``` $reply = preg_replace('/^```html\s*/i', '', $reply); $reply = preg_replace('/```$/', '', $reply); $reply = trim($reply); } // ✅ بررسی پاسخ خالی if ($reply === '') { send_to_gsheet_with_status($userData, '', 'پاسخ خالی از Gemini', $extraFields); wp_send_json_error(['message' => 'پاسخی دریافت نشد. دوباره تلاش کنید.']); } // 1) عنوان پلن را از خروجی بگیر $selectedPlanName = ''; if (preg_match('/]*class="[^"]*plan-title[^"]*"[^>]*>(.*?)<\/h2>/si', $reply, $m)) { $selectedPlanName = trim(html_entity_decode(strip_tags($m[1]))); } if ($selectedPlanName !== '' && stripos($selectedPlanName, 'flex') !== false) { $flexBackupMsg = '
پیشنهاد ویژه بک آپ: شما میتوانید دو نسخه بک آپ کامل از سرور خود را به صورت رایگان روی سرورهای دیگر ما، بدون محدودیت حجمی، ذخیره کنید
'; } // 3) جایگذاری: اگر placeholder هست، همانجا؛ وگرنه قبل از دکمه خرید if (strpos($reply, '{{flexBackupMsg}}') !== false) { $reply = str_replace('{{flexBackupMsg}}', $flexBackupMsg, $reply); } else if ($flexBackupMsg) { $reply = str_replace('
', $flexBackupMsg . '
', $reply); } $response_data = ['reply' => $reply]; if ($debug_mode) { $response_data['debug'] = [ 'model' => 'gemini-2.0-flash', 'prompt_length' => mb_strlen($prompt, 'UTF-8'), 'user_data_length' => mb_strlen($userData, 'UTF-8'), 'plans_count' => count($plansArray), 'plans_json_length' => mb_strlen($plansJsonMin, 'UTF-8'), 'plans_sample_3' => array_slice($plansArray, 0, 3), 'api_response_raw' => $body, 'payload_sent' => json_decode($payload, true), ]; } // ✅ ارسال موفق به گوگل شیت با وضعیت موفق send_to_gsheet_with_status($userData, $selectedPlanName, 'موفق ✓', $extraFields, $reply); wp_send_json_success($response_data); } // ========================================== // ✅ تابع کمکی جدید: ارسال به Google Sheet با وضعیت // ============ // ========================================== // ✅ تابع کمکی جدید: ارسال به Google Sheet با وضعیت // ========================================== function send_to_gsheet_with_status($userData, $planName, $status, $extraFields = [], $aiResponse = '') { // $webhook_url = 'https://script.google.com/macros/s/AKfycbywyfWnfcqIrys8It_c18H6lMGeQnjdpv3LLGP7qSrsUWGHntmUGtEoN0YZX2QBgn6Y/exec'; $webhook_url = 'https://script.google.com/macros/s/AKfycbzVSwIkLziKpSaPFWV0KWHXg2lZd0BpO7Yx2T9RDRjzHIhR4dpaYaNGnM_XEiyRb1wXCA/exec'; // متن خلاصه پاسخ AI $reply_text = ''; if ($aiResponse) { $reply_text = html_entity_decode(wp_strip_all_tags($aiResponse)); if (function_exists('mb_substr')) { $reply_text = mb_substr($reply_text, 0, 45000, 'UTF-8'); } else { $reply_text = substr($reply_text, 0, 45000); } } $gs_payload = array( 'name' => $extraFields['name'] ?? '', 'phone' => $extraFields['phone'] ?? '', 'website' => $extraFields['website'] ?? '', 'userData' => $userData, 'selectedPlanName' => $planName, 'aiResponseText' => $reply_text, 'geminiStatus' => $status, // ✅ فیلد جدید 'timestamp' => current_time('Y-m-d H:i:s'), // ✅ زمان دقیق ); $args = array( 'timeout' => 12, 'headers' => array('Content-Type' => 'application/json; charset=utf-8'), 'body' => wp_json_encode($gs_payload), ); wp_remote_post($webhook_url, $args); } add_action('wp_ajax_send_to_gemini_v2', 'is_handle_send_to_gemini_v2'); add_action('wp_ajax_nopriv_send_to_gemini_v2', 'is_handle_send_to_gemini_v2'); function is_handle_send_to_gemini_v2() { // ورودی‌ها $userData = isset($_POST['userData']) ? sanitize_textarea_field(wp_unslash($_POST['userData'])) : ''; $userDataJson = isset($_POST['userDataJson']) ? json_decode(wp_unslash($_POST['userDataJson']), true) : array(); $plansJson = isset($_POST['plansJson']) ? wp_unslash($_POST['plansJson']) : ''; $hostingJson = isset($_POST['hostingJson']) ? wp_unslash($_POST['hostingJson']) : ''; $formType = isset($_POST['formType']) ? sanitize_text_field(wp_unslash($_POST['formType'])) : ''; // A یا B if ($userData === '') { wp_send_json_error(['message' => 'داده‌های کاربر دریافت نشد.']); } // نرمال‌سازی: پلن‌ها (اختیاری ولی توصیه‌شده) $normalize_unlimited = function($v){ return is_string($v) && preg_match('/unlimited/i',$v) ? 'نامحدود' : $v; }; $plansArray = []; if ($plansJson) { $raw = json_decode($plansJson, true); if (is_array($raw)) { foreach ($raw as $p) { $plansArray[] = [ 'planName' => $p['plan_name'] ?? $p['name'] ?? '', 'planType' => $p['type'] ?? '', // اگر بود 'location' => $p['location'] ?? '', // موقعیت مکانی 'storage' => $p['storage'] ?? '', // حجم هارد 'bandwidth' => $normalize_unlimited($p['bandwidth'] ?? $p['traffic'] ?? ''), // ترافیک 'controlPanel' => $p['control_panel'] ?? '', // کنترل پنل 'dns' => $p['dns'] ?? '', 'support' => $p['support'] ?? '', 'warranty' => $p['warranty'] ?? '', // اگر در داده‌ات این کلید را داشته باشی 'features' => (isset($p['features']) && is_array($p['features'])) ? array_values($p['features']) : [], 'buyLink' => $p['buyLink'] ?? $p['link'] ?? $p['url'] ?? '', ]; } } } // هاستینگ با similar_to (اختیاری) $hostingMerged = []; if ($hostingJson) { $h = json_decode($hostingJson, true); if (is_array($h)) { foreach ($h as $catKey => $cat) { $url = isset($cat['url']) ? esc_url_raw($cat['url']) : ''; $plans = isset($cat['plans']) && is_array($cat['plans']) ? $cat['plans'] : []; foreach ($plans as $pl) { $plansArray[] = [ 'planName' => $pl['plan_name'] ?? $pl['name'] ?? '', 'planType' => $catKey, // wordpress_hosting / woocommerce_hosting / ... 'location' => $pl['location'] ?? '', 'storage' => $pl['storage'] ?? '', 'bandwidth' => $normalize_unlimited($pl['bandwidth'] ?? $pl['traffic'] ?? ''), 'controlPanel' => $pl['control_panel'] ?? '', 'dns' => $pl['dns'] ?? '', 'support' => $pl['support'] ?? '', 'warranty' => $pl['warranty'] ?? '', 'features' => (isset($pl['features']) && is_array($pl['features'])) ? array_values($pl['features']) : [], 'buyLink' => $pl['buyLink'] ?? $url, ]; } } } } // محدودیت منطقی if (count($plansArray) > 400) $plansArray = array_slice($plansArray, 0, 400); $plansJsonMin = wp_json_encode($plansArray, JSON_UNESCAPED_UNICODE | JSON_UNESCAPED_SLASHES); // پرامپت جدید (برای دو فرم A/B) // A = دارای سایت: تاکید بر پلتفرم فعلی، مشکلات، ترافیک // B = بدون سایت: تاکید بر نوع پروژه، ترجیحات مدیریت، اولویت‌ها $prompt_header = "نقش شما «مشاور خرید هاست و سرور» است. از بین لیست پلن‌های ارائه‌شده (VPS/Dedicated + دسته‌های هاست)، دقیقا یک پلن مناسب را انتخاب کن و فقط HTML خالص (بدون بک‌تیک) برگردان."; $prompt_rules = implode("\n", [ "- فقط از داده‌های JSON استفاده کن و چیزی اختراع نکن.", "- اگر هرجا Unlimited دیدی آن را به «نامحدود» تبدیل کن.", "- خروجی باید دقیقا همان HTML داده‌شده را برگرداند و فقط جای {{...}} ها را با مقادیر پر کند.", "- اگر هر یک از فیلدهای زیر خالی بود، به جای مقدار آن «» بگذار:", " {{planName}}, {{storage}}, {{bandwidth}}, {{controlPanel}}, {{dns}}, {{support}}, {{location}}, {{warranty}}, {{featuresList}}", "- برای «سایر ویژگی‌ها»: اگر آرایه features موجود بود، {{featuresList}} را با
  • ...
بساز؛ وگرنه برای {{featuresList}} «» قرار بده.", "- برای «نام پلن» از planName استفاده کن (نه planType).", "- برای «حجم هارد» از storage، برای «ترافیک» از bandwidth، برای «کنترل پنل» از controlPanel، برای «DNS» از dns، برای «پشتیبانی» از support، برای «موقعیت مکانی» از location، برای «گارانتی استفاده از سرویس» از warranty استفاده کن.", "- مقدار {{buyLink}} را دقیقا از کلید buyLink همان پلن انتخابی بگذار." ]); $prompt_html = '

پیشنهاد هوشمند ما برای شما

بر اساس پاسخ‌های شما، این پلن بیشترین انطباق را با نیازهایتان دارد:

{{planName}}

  • نام پلن : {{planName}}
  • حجم هارد: {{storage}}
  • ترافیک: {{bandwidth}}
  • کنترل پنل: {{controlPanel}}
  • DNS : {{dns}}
  • پشتیبانی: {{support}}
  • موقعیت مکانی: {{location}}
  • گارانتی استفاده از سرویس: 14 روز
  • سایر ویژگی‌ها: {{featuresList}}
'; $prompt_user_block = "[نوع فرم]: " . ($formType === 'A' ? 'دارای سایت' : ($formType === 'B' ? 'بدون وب‌سایت' : 'نامشخص')) . "\n\n[اطلاعات کاربر]\n" . $userData; $prompt_plans = "[لیست پلن‌ها — JSON]\n" . $plansJsonMin; $prompt = implode("\n\n", [ $prompt_header, $prompt_rules, $prompt_html, $prompt_user_block, $prompt_plans ]); // فراخوانی Gemini // $api_key = 'AIzaSyCuMe-s-NxY3cFLHTX3IgW5MhzJLndpQaU'; // $url = 'https://generativelanguage.googleapis.com/v1beta/models/gemini-2.0-flash:generateContent?key=' . $api_key; // if (!$api_key) { // wp_send_json_error(['message' => 'کلید API تنظیم نشده است.']); // } // $url = 'https://generativelanguage.googleapis.com/v1beta/models/gemini-2.0-flash:generateContent?key=' . rawurlencode($api_key); $access_token = my_get_gemini_access_token(); if (!$access_token) { gemini_log(['type' => 'auth_error', 'message' => 'Failed to get access token in v2']); wp_send_json_error(['message' => 'خطا در دریافت Access Token از Google']); } $url = 'https://generativelanguage.googleapis.com/v1beta/models/gemini-2.0-flash:generateContent'; // Log connection attempt (for both services) gemini_log([ 'type' => 'gemini_connect', 'service' => 'v2', 'url' => $url, 'payload_len' => isset($payload) ? strlen($payload) : null, 'extraFields' => isset($extraFields) ? $extraFields : null, ]); $payload = wp_json_encode([ 'contents' => [ ['parts' => [['text' => $prompt]]] ] ], JSON_UNESCAPED_UNICODE | JSON_UNESCAPED_SLASHES); $res = wp_remote_post($url, [ 'headers' => [ 'Content-Type' => 'application/json; charset=utf-8', 'Authorization' => 'Bearer ' . $access_token, // ✅ اضافه شد ], 'body' => $payload, 'timeout' => 45, ]); if (is_wp_error($res)) { gemini_log([ 'type' => 'wp_error_v2', 'error' => $res->get_error_message(), ]); wp_send_json_error(['message' => $res->get_error_message()]); } $code = wp_remote_retrieve_response_code($res); $raw_body = wp_remote_retrieve_body($res); $headers = wp_remote_retrieve_headers($res); $body = json_decode($raw_body, true); // Log HTTP details when debug is enabled if (gemini_is_debug_mode()) { gemini_log([ 'type' => 'http_debug', 'service' => 'v2', 'http_code' => $code, 'headers' => $headers, 'raw_body' => $raw_body, ]); } if ($code !== 200) { gemini_log([ 'type' => 'api_error_v2', 'http_code' => $code, 'headers' => $headers, 'raw_body' => $raw_body, 'response' => $body, ]); wp_send_json_error([ 'message' => 'سرویس موقتاً در دسترس نیست.' ]); } // Log successful response (minimal) gemini_log([ 'type' => 'gemini_ok', 'service' => 'v2', 'http_code' => $code, ]); $reply = ''; if (!empty($body['candidates'][0]['content']['parts'])) { foreach ($body['candidates'][0]['content']['parts'] as $part) { if (!empty($part['text'])) { $reply = $part['text']; break; } } } if ($reply) { // حذف fence و اسکریپت و پاکسازی پایه $reply = preg_replace('/^```html\s*/i', '', $reply); $reply = preg_replace('/```$/', '', $reply); $reply = preg_replace('/]*>(.*?)<\/script>/is', '', $reply); $reply = trim( wp_kses_post($reply) ); } if ($reply === '') wp_send_json_error(['message' => 'پاسخی دریافت نشد.']); wp_send_json_success(['reply' => $reply]); } add_action('wp_ajax_send_to_google_sheet2', 'send_to_google_sheet2'); add_action('wp_ajax_nopriv_send_to_googl add_action('wp_ajax_send_to_google_sheet2', 'send_to_google_sheet2'); add_action('wp_ajax_nopriv_send_to_google_sheet2', 'send_to_google_sheet2'); function send_to_google_sheet2() { // گرفتن داده‌ها از درخواست $json = file_get_contents('php://input'); $data = json_decode($json, true); // آماده‌سازی payload برای Google Apps Script $payload = json_encode([ 'name' => $data['name'] ?? '', 'phone' => $data['phone'] ?? '', 'formId' => $data['formId'] ?? '', 'userData' => $data['userData'] ?? '' ]); // آدرس Google Apps Script // $scriptUrl = 'https://script.google.com/macros/s/AKfycbzVGjdRzFBEN8rpKqqThD96agccp0JKIRUf1Nkd8UfwrWU-UXfF0HONfEun_d2dLioT/exec'; $scriptUrl = 'https://script.google.com/macros/s/AKfycbw9l4nG9Cf7FO5aVugNjLK_nVzYHMWMfrgwTlnR34DaaeYci9jjngEsVyaS3al9yLRB/exec'; $response = wp_remote_post($scriptUrl, [ 'headers' => ['Content-Type' => 'application/json'], 'body' => $payload ]); // بررسی پاسخ if (is_wp_error($response)) { wp_send_json_error(['message' => 'خطا در ارتباط ']); } $body = wp_remote_retrieve_body($response); wp_send_json(json_decode($body, true)); }